﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using Estructuras.Comunes;
using Estructuras.Estructura;

namespace Estructuras.Funciones.Transformar
{
    public static class FuncionesCondicion
    {
        /// <summary>
        /// Comprueba si se cumple la condición indicada sobre el registro proporcionado.
        /// </summary>
        /// <param name="formato">Estructura del registro de datos</param>
        /// <param name="registro">Registro de datos</param>
        /// <param name="campoOrigen">Campo origen sobre el que aplicar la transformación</param>
        /// <param name="campoDestino">Campo destino sobre el que aplicar la transformación</param>
        /// <param name="funcion">Función a aplicar</param>
        /// <param name="parametrosEntrada">Parámetros de la función a aplicar</param>
        public static bool EjecutarComprobacion(Estructura.Estructura formato, ref string registro, string campo, string funcion, List<string> parametros)
        {
            string datoComprobar = formato.obtenerValorCampo(registro, campo);
            try
            {
                char[] del = { ' ' };
                int longitud = 0;
                string valorCampo = string.Empty;
                long temp = 0;
                long temp1 = 0;
                Regex expresion = null;
                DateTime fecha;
                DateTime fecha1;
                switch (funcion)
                {
                    case "longitud_mayor_valor":
                        longitud = Int32.Parse(parametros[0]);
                        return (datoComprobar.TrimEnd(del).Length > longitud);
                    case "longitud_menor_valor":
                        longitud = Int32.Parse(parametros[0]);
                        return (datoComprobar.TrimEnd(del).Length < longitud);
                    case "longitud_mayor_campo":
                        valorCampo = formato.obtenerValorCampo(registro, parametros[0]);
                        return (datoComprobar.TrimEnd(del).Length > valorCampo.TrimEnd(del).Length);
                    case "longitud_menor_campo":
                        valorCampo = formato.obtenerValorCampo(registro, parametros[0]);
                        return (datoComprobar.TrimEnd(del).Length < valorCampo.TrimEnd(del).Length);
                    case "contiene":
                        return (datoComprobar.TrimEnd(del).Contains(parametros[0]));
                    case "expresion_regular":
                        expresion = new Regex(parametros[0]);
                        return expresion.Match(datoComprobar).Success;
                    case "es_numero":
                        try
                        {
                            temp = long.Parse(datoComprobar);
                            return true;
                        }
                        catch (Exception)
                        { return false; }
                    case "numero_mayor_valor":
                        try
                        {
                            temp = long.Parse(datoComprobar);
                            temp1 = long.Parse(parametros[0]);
                            return (temp > temp1);
                        }
                        catch (Exception)
                        { return false; }
                    case "numero_menor_valor":
                        try
                        {
                            temp = long.Parse(datoComprobar);
                            temp1 = long.Parse(parametros[0]);
                            return (temp < temp1);
                        }
                        catch (Exception)
                        { return false; }
                    case "numero_mayor_campo":
                        try
                        {
                            temp = long.Parse(datoComprobar);
                            temp1 = long.Parse(formato.obtenerValorCampo(registro, parametros[0]));
                            return (temp > temp1);
                        }
                        catch (Exception)
                        { return false; }
                    case "numero_menor_campo":
                        try
                        {
                            temp = long.Parse(datoComprobar);
                            temp1 = long.Parse(formato.obtenerValorCampo(registro, parametros[0]));
                            return (temp < temp1);
                        }
                        catch (Exception)
                        { return false; }
                    case "es_fecha":
                        try
                        {
                            fecha = ConvertirAFecha(datoComprobar, parametros[0]);
                            return true;
                        }
                        catch (Exception)
                        { return false; }
                    case "fecha_mayor_valor":
                        try
                        {
                            fecha = ConvertirAFecha(datoComprobar, parametros[0]);
                            fecha1 = ConvertirAFecha(parametros[1], parametros[0]);
                            return (fecha > fecha1);
                        }
                        catch (Exception)
                        { return false; }
                    case "fecha_menor_valor":
                        try
                        {
                            fecha = ConvertirAFecha(datoComprobar, parametros[0]);
                            fecha1 = ConvertirAFecha(parametros[1], parametros[0]);
                            return (fecha < fecha1);
                        }
                        catch (Exception)
                        { return false; }
                    case "fecha_mayor_campo":
                        try
                        {
                            fecha = ConvertirAFecha(datoComprobar, parametros[0]);
                            fecha1 = ConvertirAFecha(formato.obtenerValorCampo(registro, parametros[1]), parametros[0]);
                            return (fecha > fecha1);
                        }
                        catch (Exception)
                        { return false; }
                    case "fecha_menor_campo":
                        try
                        {
                            fecha = ConvertirAFecha(datoComprobar, parametros[0]);
                            fecha1 = ConvertirAFecha(formato.obtenerValorCampo(registro, parametros[1]), parametros[0]);
                            return (fecha < fecha1);
                        }
                        catch (Exception)
                        { return false; }
                    default:
                        throw new Excepcion(Constantes.ErrorFuncionNoExiste + funcion, Constantes.CodigoErrorFuncionNoExiste);
                }
            }
            catch (Excepcion ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new Excepcion(Constantes.ErrorEjecutarFuncion + funcion + ": " + ex.Message, Constantes.CodigoErrorEjecutarFuncion);
            }
        }

        public static string[] formatosFechaValidos = { "yyyyMMdd", "dd/MM/yyyy", "d/M/yyyy", "MM/dd/yyyy", "yyyyddMM", "dd-MM-yyyy", "d-M-yyyy", "MM-dd-yyyy" };

        /// <summary>
        /// Convierte un dato con un determinado formato en una fecha.
        /// </summary>
        /// <param name="dato">Dato a convertir</param>
        /// <param name="formato">Formato del dato</param>
        /// <returns>Fecha</returns>
        public static DateTime ConvertirAFecha(string dato, string formato)
        {
            string[] datos;
            string[] separadores = new string[1];
            switch (formato)
            {
                case "yyyyMMdd":
                    return new DateTime(int.Parse(dato.Substring(0, 4)), int.Parse(dato.Substring(4, 2)), int.Parse(dato.Substring(6, 2)));
                case "dd/MM/yyyy":
                case "d/M/yyyy":
                    separadores[0] = "/";
                    datos = dato.Split(separadores, StringSplitOptions.None);
                    if (datos.Length != 3)
                        throw new Excepcion(Constantes.ErrorFormatoFechaNoValido + formato, Constantes.CodigoErrorFormatoFechaNoValido);
                    return new DateTime(int.Parse(datos[2]), int.Parse(datos[1]), int.Parse(datos[0]));
                case "MM/dd/yyyy":
                    separadores[0] = "/";
                    datos = dato.Split(separadores, StringSplitOptions.None);
                    if (datos.Length != 3)
                        throw new Excepcion(Constantes.ErrorFormatoFechaNoValido + formato, Constantes.CodigoErrorFormatoFechaNoValido);
                    return new DateTime(int.Parse(datos[2]), int.Parse(datos[0]), int.Parse(datos[1]));
                case "dd-MM-yyyy":
                case "d-M-yyyy":
                    separadores[0] = "-";
                    datos = dato.Split(separadores, StringSplitOptions.None);
                    if (datos.Length != 3)
                        throw new Excepcion(Constantes.ErrorFormatoFechaNoValido + formato, Constantes.CodigoErrorFormatoFechaNoValido);
                    return new DateTime(int.Parse(datos[2]), int.Parse(datos[1]), int.Parse(datos[0]));
                case "MM-dd-yyyy":
                    separadores[0] = "-";
                    datos = dato.Split(separadores, StringSplitOptions.None);
                    if (datos.Length != 3)
                        throw new Excepcion(Constantes.ErrorFormatoFechaNoValido + formato, Constantes.CodigoErrorFormatoFechaNoValido);
                    return new DateTime(int.Parse(datos[2]), int.Parse(datos[0]), int.Parse(datos[1]));
                case "yyyyddMM":
                    return new DateTime(int.Parse(dato.Substring(0, 4)), int.Parse(dato.Substring(6, 2)), int.Parse(dato.Substring(4, 2)));
                default:
                    throw new Excepcion(Constantes.ErrorFormatoFechaNoValido + formato, Constantes.CodigoErrorFormatoFechaNoValido);
            }
        }
    }
}
